package com.cxy.common.config;

import com.cxy.common.boot.CxyCloudConstants;
import com.cxy.common.util.ClassUtils;
import com.cxy.common.util.EncryptWrappedUtils;
import com.cxy.common.util.UnicodeReader;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.io.Resource;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/*********************************************************
 * 文件名称：CxyConfigLoad.java
 * 系统名称：CXY自定义系统
 * 模块名称：com.cxy.common.config
 * 功能说明：配置加载
 * 开发人员 @author：caoxy31978
 * 开发时间 @date：2023/7/4 15:46
 * 修改记录：程序版本  修改日期  修改人员  修改单号  修改说明
 *********************************************************/
@Order(100)
@Slf4j
public class CxyConfigLoad implements EnvironmentPostProcessor {
    private static final String CONFIG_LOCATION = "config.location";
    private final Log deferredLog;

    public CxyConfigLoad(DeferredLogFactory logFactory) {
        this.deferredLog = logFactory.getLog(ConfigUtils.class);
    }
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        Map<String,Object> map = new HashMap<>();
        try {
            String configLocations = environment.getProperty(CONFIG_LOCATION);
            if (StringUtils.isNotBlank(configLocations)){
                getProperty(map, CxyCloudConstants.COMMA_SPLIT_PATTERN.split(configLocations));
            }
            environment.getPropertySources().addLast(new MapPropertySource("locationConfig", map));
        }catch (Throwable e){
            throw new RuntimeException("配置处理异常",e);
        }
    }

    private void getProperty(Map<String, Object> map, String[] locations) throws Exception {
        if (locations != null) {
            for (String location : locations) {
                if (location.startsWith("classpath:")) {
                    Resource[] resources = ClassUtils.scanFile(location.replace("classpath:", "").trim());
                    for (Resource resource : resources) {
                        getPropertyFromResource(map, resource);
                    }
                } else if (location.startsWith("classpath*:")) {
                    Resource[] resources = ClassUtils.scanFile(location.replace("classpath*:", "").trim());
                    for (Resource resource : resources) {
                        getPropertyFromResource(map, resource);
                    }
                } else {
                    getPropertyFromPath(map, location);
                }
            }
        }
    }
    private void getPropertyFromResource(Map<String, Object> map, Resource resource) throws Exception {
        try(UnicodeReader ur = new UnicodeReader(resource.getInputStream(), "UTF-8")) {
            Properties p = new Properties();
            p.load(ur);
            getPropertyFromProperties(map, p);
        }
    }

    /**
     * 加载文件或文件夹下所有文件，不包含子文件夹
     * @param map
     * @param path
     * @throws Exception
     */
    private void getPropertyFromPath(Map<String, Object> map, String path) throws Exception {
        File file = new File(path);
        File[] files;
        if (file.isDirectory()) {
            files = file.listFiles();
        }else {
            files = new File[]{file};
        }
        for (File f : files) {
            if (f.exists() && f.isFile() && f.getName().endsWith(".properties")) {
                try(InputStream is = new FileInputStream(f);) {
                    Properties p = new Properties();
                    p.load(new UnicodeReader(is, "UTF-8"));
                    getPropertyFromProperties(map, p);
                }
            }
        }
/*        try (Stream<Path> stream =  Files.walk(Paths.get(path));){
            stream.filter(Files::isRegularFile)
                    .filter(p ->p.toString().endsWith(".properties"))
                    .forEach(p->{
                        try(InputStream is = new FileInputStream(p.toFile())) {
                            Properties properties = new Properties();
                            properties.load(new UnicodeReader(is, "UTF-8"));
                            this.getPropertyFromProperties(map, properties);
                        } catch (Exception e) {
                        }
                    });
        }*/
    }

    /**
     * 将参数转换到map中，先进的优先级高，后进的重复项舍弃掉
     * @param map
     * @param p
     * @throws Exception
     */
    private void getPropertyFromProperties(Map<String, Object> map, Properties p) throws Exception {
        Enumeration<?> e = p.propertyNames();
        while(e.hasMoreElements()) {
            String strKey = (String)e.nextElement();
            String strValue = p.getProperty(strKey);
            if (!map.containsKey(strKey)) {
                map.put(strKey, EncryptWrappedUtils.getEncryptWrappedValue(strValue));
            }
        }
    }

}
